package com.cjl.demo.map;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>Copyright: All Rights Reserved</p>
 * <p>Company:    http://www.ronglian.com</p>
 * <p>Description: 单独实现HashMap </p>
 * <p>Author:jlchen/陈金梁</p>
 * <p>Date:  2018/3/25</p>
 */
public class MyHashMap<V, T> {

    /**
     * <p>Description: Map存储对象:用key和value定义一个简单的Map数据结构,next用于解决桶冲突</p>
     * <p>@Author:jlchen/陈金梁</p>
     *
     * @date 2018/3/25 18:55
     * @return
     */
    public class EntrySet<V, T> {
        private V key;
        private T value;
        private EntrySet next;

        public EntrySet() {

        }

        public EntrySet(V key, T value) {
            this.key = key;
            this.value = value;
        }

        public V getKey() {
            return key;
        }

        public void setKey(V key) {
            this.key = key;
        }

        public T getValue() {
            return value;
        }

        public void setValue(T value) {
            this.value = value;
        }

        public EntrySet getNext() {
            return next;
        }

        public void setNext(EntrySet next) {
            this.next = next;
        }
    }

    /**
     * <p>Description: 无参构造和有参构造</p>
     * <p>@Author:jlchen/陈金梁</p>
     *
     * @date 2018/3/25 19:37
     * @return
     */
    private EntrySet[] map;
    /**
     * map初始大小
     */
    private int size = 16;


    public MyHashMap() {
        map = new EntrySet[size];
    }

    public MyHashMap(int size) {
        //保证数组的容量是2的幂次。
        int cal = 1;
        while (cal <size){
            cal <<= 1; //右移一位，相当于乘以2，右移两位，相当于乘以4
        }
        map = new EntrySet[cal];
    }

    /**
     * <p>Description: hash化</p>
     * <p>@Author:jlchen/陈金梁</p>
     *
     * @return
     * @date 2018/3/25 19:10
     */
    public int hash(Object obj) {
        return obj.hashCode();
    }

    /**
     * <p>Description: 插入</p>
     * <p>@Author:jlchen/陈金梁</p>
     *
     * @return 原始元素值
     * @date 2018/3/25 19:01
     */
    public T put(V v, T t) {
        if (null == v) {
            return null;
        }
        int w = hash(v) % map.length;
        EntrySet e = map[w];
        while (null != e) {
            if (v.equals(e.getKey())) {
                e.setValue(t);
                return t;
            }
        }
        EntrySet tmp = new EntrySet(v, t);
        tmp.setNext(e);
        map[w] = tmp;
        return t;

    }

    /**
     * <p>Description: 获取值：根据key返回value，如果是空或者没有和key对应的value返回空</p>
     * <p>@Author:jlchen/陈金梁</p>
     *
     * @return
     * @date 2018/3/25 19:22
     */
    public T get(V v) {
        if (null == v) {
            return null;
        }
        T t = null;
        int w = hash(v) % map.length;
        EntrySet e = map[w];
        //如果找到了对应的桶，那么就沿着链寻找看看与key对应的value是否存在
        while (null != e) {
            if (v.equals(e.getKey())) {
                t = (T) e.getValue();
                break;
            }
        }
        return t;
    }


    public static void main(String[] args) {
        MyHashMap<String, String> map = new MyHashMap<>();
        map.put("name", "test");
        map.put("value", "tmp");
        map.put("", "null");
        map.put(null, "null");

        System.out.println("name = [" + map.get("name") + "]");
        System.out.println("value = [" + map.get("value") + "]");

        Map<String, String> tmp = new HashMap<>();
        tmp.put(null,"t");
        System.out.println("args = [" + tmp.get(null) + "]");

    }
}
